import 'dart:io';
import 'dart:ui' as ui show Codec, ImmutableBuffer;

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';

import '../../utils/native/oss_native_util.dart';

/// 用于兼容 photo view
class OSSImageProvider extends ImageProvider<OSSImageProvider> {
  final String ossKey;

  /// The file to decode into an image.

  final double scale;

  const OSSImageProvider(this.ossKey, {this.scale = 1.0});

  @override
  Future<OSSImageProvider> obtainKey(ImageConfiguration configuration) {
    return SynchronousFuture<OSSImageProvider>(this);
  }

  @override
  ImageStreamCompleter loadImage(
      OSSImageProvider key, ImageDecoderCallback decode) {
    return MultiFrameImageStreamCompleter(
      codec: _loadAsync(key, decode),
      scale: key.scale,
      debugLabel: key.ossKey,
      informationCollector: () => <DiagnosticsNode>[
        ErrorDescription('ossKey: ${key.ossKey}'),
      ],
    );
  }

  Future<ui.Codec> _loadAsync(
      OSSImageProvider key, ImageDecoderCallback decode) async {
    assert(key == this);

    var ossResult = await OssNativeUtil.ossDownloadImage(
        ossKey: ossKey, scaleType: BoxFit.none);
    if (ossResult == null) {
      throw StateError('$ossKey 下载失败.');
    }

    File file = File(ossResult.filePath);
    final Uint8List bytes = await file.readAsBytes();
    if (bytes.lengthInBytes == 0) {
      // The file may become available later.
      PaintingBinding.instance.imageCache.evict(key);
      throw StateError(
          '${ossResult.filePath} is empty and cannot be loaded as an image.');
    }

    return decode(await ui.ImmutableBuffer.fromUint8List(bytes));
  }

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is OSSImageProvider &&
        other.ossKey == ossKey &&
        other.scale == scale;
  }

  @override
  int get hashCode => Object.hash(ossKey, scale);

  @override
  String toString() =>
      '${objectRuntimeType(this, 'OSSImage')}("ossKey: $ossKey", scale: $scale)';
}
